﻿using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace AvalonAdmin.Helpers
{

    #region 调用方法
    // 异常步调用（推荐）
    // 测试HTTPS域名
    //var result = await UdpValidator.ValidateUdpAsync(
    //    "https://example.com",
    //    port: 161,
    //    timeoutMs: 2000,
    //    CancellationToken.None);

    // 测试IPv6地址
    //var ipv6Result = await UdpValidator.ValidateUdpAsync(
    //    "fe80::1",
    //    port: 5353,
    //    timeoutMs: 3000);

    // 同步调用（仅用于非 UI 场景）
    //var ipResult = UdpValidator.ValidateUdp("192.168.1.1", 8080);
    #endregion

    /// <summary>
    /// UDP 测试结果
    /// </summary>
    public record UdpTestResult(bool Success, string Endpoint);

    /// <summary>
    /// UDP可达性验证工具类（支持IP和域名，自动处理协议头，优化异常处理）
    /// </summary>
    public class UdpValidator
    {
        /// <summary>
        /// 异常步验证IP或域名的UDP可达性（推荐用于非阻塞场景）
        /// </summary>
        /// <param name="input">IP地址或HTTP/HTTPS域名</param>
        /// <param name="port">目标UDP端口（默认53）</param>
        /// <param name="timeoutMs">超时时间（默认1000ms）</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>包含验证结果和详细信息的字符串</returns>
        public static async Task<string> ValidateTcpAsync(string input, int port = 53, int timeoutMs = 1000, CancellationToken cancellationToken = default)
        {
            try
            {
                if (string.IsNullOrWhiteSpace(input))
                    return "错误：输入为空";

                var host = StripProtocol(input);
                if (string.IsNullOrWhiteSpace(host))
                    return "错误：无法解析主机名";

                var addresses = await Dns.GetHostAddressesAsync(host, cancellationToken);
                if (addresses.Length == 0)
                    return "错误：无法解析IP地址";

                var tasks = new List<Task<UdpTestResult>>();
                foreach (var address in addresses)
                {
                    cancellationToken.ThrowIfCancellationRequested();
                    tasks.Add(TestTcpConnectionAsync(address, port, timeoutMs, cancellationToken));
                }

                // 等待所有任务完成
                await Task.WhenAll(tasks);

                foreach (var task in tasks)
                {
                    var result = await task;
                    if (result.Success)
                    {
                        return $"成功：{result.Endpoint} 端口{port}可用";
                    }
                }

                return "失败：所有IP均未响应";
            }
            catch (OperationCanceledException)
            {
                return "操作已取消";
            }
            catch (SocketException ex) when (ex.SocketErrorCode == SocketError.TimedOut)
            {
                return "错误：连接超时";
            }
            catch (SocketException ex) when (ex.SocketErrorCode == SocketError.AddressNotAvailable)
            {
                return "错误：目标地址不可用";
            }
            catch (Exception ex)
            {
                return $"错误：{ex.Message}";
            }
        }

        /// <summary>
        /// 同步验证IP或域名的UDP可达性（不推荐用于UI线程）
        /// </summary>
        public static string ValidateUdp(string input, int port = 53, int timeoutMs = 1000)
        {
            return ValidateTcpAsync(input, port, timeoutMs).GetAwaiter().GetResult();
        }

        /// <summary>
        /// 剥离协议头并解析主机名
        /// </summary>
        private static string StripProtocol(string input)
        {
            if (string.IsNullOrWhiteSpace(input))
                return string.Empty;

            // 移除协议头（http:// 或 https://）
            input = input.Trim();
            if (input.StartsWith("http://", StringComparison.OrdinalIgnoreCase))
            {
                input = input.Substring(7); // "http://".Length = 7
            }
            else if (input.StartsWith("https://", StringComparison.OrdinalIgnoreCase))
            {
                input = input.Substring(8); // "https://".Length = 8
            }

            // 处理带端口的主机（如 example.com:8080）
            int portIndex = input.IndexOf(':');
            if (portIndex > 0)
            {
                input = input.Substring(0, portIndex);
            }

            // 处理路径（如 example.com/path）
            int pathIndex = input.IndexOf('/');
            if (pathIndex > 0)
            {
                input = input.Substring(0, pathIndex);
            }

            // 处理IPv6地址（如 [fe80::1]:80）
            if (input.StartsWith("[") && input.Contains("]"))
            {
                int endIndex = input.IndexOf(']');
                if (endIndex > 0)
                {
                    input = input.Substring(1, endIndex - 1);
                }
            }

            return input.Trim();
        }

        /// <summary>
        /// 异常步UDP连接测试
        /// </summary>
        private static async Task<UdpTestResult> TestTcpConnectionAsync(IPAddress address, int port, int timeoutMs, CancellationToken cancellationToken)
        {

            using (var client = new TcpClient())
            {
                var cts = new CancellationTokenSource();
                cts.CancelAfter(1000); // 设置1秒超时

                try
                {
                    // 使用异常步连接并等待超时
                    var connectTask = client.ConnectAsync(address, port);
                    var completedTask = await Task.WhenAny(connectTask, Task.Delay(Timeout.Infinite, cts.Token));

                    if (completedTask == connectTask && connectTask.Status == TaskStatus.RanToCompletion)
                    {
                        return new UdpTestResult(true, FormatEndpoint(address, port));
                    }
                    else
                    {
                        // 超时或连接失败
                        return new UdpTestResult(false, FormatEndpoint(address, port));
                    }
                }
                catch (OperationCanceledException)
                {
                    // 超时取消
                    return new UdpTestResult(false, FormatEndpoint(address, port));
                }
                catch
                {
                    // 其他连接错误
                    return new UdpTestResult(false, FormatEndpoint(address, port));
                }
            }

            //using var client = new UdpClient();
            //client.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);

            //try
            //{
            //    // 绑定随机本地端口
            //    client.Client.Bind(new IPEndPoint(IPAddress.Any, 0));

            //    // 发送数据
            //    var sendEndpoint = new IPEndPoint(address, port);
            //    await client.SendAsync(Encoding.UTF8.GetBytes("PING"), sendEndpoint, cancellationToken);

            //    // 显式设置接收超时
            //    using var receiveCts = new CancellationTokenSource(timeoutMs);
            //    using var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, receiveCts.Token);

            //    var receiveTask = client.ReceiveAsync(linkedCts.Token).AsTask();
            //    var completedTask = await Task.WhenAny(receiveTask, Task.Delay(timeoutMs, linkedCts.Token));

            //    // 检查是否是接收任务完成
            //    if (completedTask == receiveTask)
            //    {
            //        var response = await receiveTask;
            //        return new UdpTestResult(true, FormatEndpoint(address, port));
            //    }

            //    return new UdpTestResult(false, FormatEndpoint(address, port)); // 超时
            //}
            //catch (OperationCanceledException)
            //{
            //    return new UdpTestResult(false, FormatEndpoint(address, port));
            //}
            //catch (SocketException ex) when (ex.SocketErrorCode == SocketError.TimedOut)
            //{
            //    return new UdpTestResult(false, FormatEndpoint(address, port));
            //}
            //catch (Exception ex)
            //{
            //    Console.WriteLine($"UDP 测试异常 ({FormatEndpoint(address, port)}): {ex.Message}");
            //    return new UdpTestResult(false, FormatEndpoint(address, port));
            //}
        }

        /// <summary>
        /// 格式化端点信息
        /// </summary>
        private static string FormatEndpoint(IPAddress address, int port)
        {
            return address.AddressFamily == AddressFamily.InterNetworkV6
                ? $"[{address}]:{port}"
                : $"{address}:{port}";
        }
    }



    /// <summary>
    /// SocketException扩展方法
    /// </summary>
    public static class SocketExceptionExtensions
    {
        /// <summary>
        /// 判断是否为超时异常
        /// </summary>
        public static bool IsTimeout(this SocketException ex) => ex.NativeErrorCode == 10060;

        /// <summary>
        /// 判断是否为地址不可用
        /// </summary>
        public static bool IsAddressNotAvailable(this SocketException ex) => ex.NativeErrorCode == 11001;
    }
}

